/*
Disclaimer of Warranty: THE PACKAGE
IS PROVIDED BY THE COPYRIGHT HOLDER
AND CONTRIBUTORS "AS IS' AND WITHOUT
ANY EXPRESS OR IMPLIED WARRANTIES.
THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT
ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW.
UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR
WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE
OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

(c) Copyright 2013 Edward Principe
All Rights Reserved
*/
#include "stdafx.h"
#include "errrep.h"

//////////////////////////////////////////////////////////////////////
// Init: Initializes the class
//////////////////////////////////////////////////////////////////////
void ErrRep::Init()
{
	_list_errors.erase(_list_errors.begin(), _list_errors.end());
	_fatal_errors = _errors = _warnings = _messages = 0;
}

///////////////////////////////////////////////////////////////////////
// Copy: Copies class
///////////////////////////////////////////////////////////////////////
void ErrRep::Copy(const ErrRep& rhs)
{
	if (this == &rhs)
		return;

	_list_errors = rhs._list_errors;
	_fatal_errors = rhs._fatal_errors;
	_errors = rhs._errors;
	_warnings = rhs._warnings;
	_messages = rhs._messages;
}

///////////////////////////////////////////////////////////////////////
// CalcErrors: Calculate the error statistics
//////////////////////////////////////////////////////////////////////
void ErrRep::CalcErrors()
{
	// Rest error counters
	_fatal_errors = _errors = _warnings = _messages = 0;

	// Locals
	for (list<TokEx>::iterator i = _list_errors.begin(); i != _list_errors.end(); i++)
	{
		switch (i->GetSev())
		{
		case(SEV_MESSAGE) :
			_messages++;
			break;

		case(SEV_WARNING) :
			_warnings++;
			break;

		case(SEV_ERROR) :
			_errors++;
			break;

		case(SEV_FATAL) :
			_fatal_errors++;
			break;

		default:
			throw new InternalError(TEXT("No such severity in ErrRep::CalcErrors"));
		}
	}
}

////////////////////////////////////////////////////////////////////////////////////////
// Set: Sets Error
////////////////////////////////////////////////////////////////////////////////////////
void ErrRep::Set(const ErrRep& rhs)
{
	// Copy errors
	for (list<TokEx>::const_iterator i = rhs._list_errors.begin(); i != rhs._list_errors.begin(); i++)
	{
		_list_errors.push_back(static_cast<TokEx>(*i));
	}

	// Calculate statistics
	_fatal_errors += rhs._fatal_errors;
	_errors += rhs._errors;
	_warnings += rhs._warnings;
	_messages += rhs._messages;
}

void ErrRep::Set(const TokEx& rhs)
{
	// Get error
	_list_errors.push_back(rhs);

	// Calculate statistics
	switch (rhs.GetSev())
	{
	case(SEV_FATAL) :
		_fatal_errors++;
		break;

	case(SEV_ERROR) :
		_errors++;
		break;

	case(SEV_WARNING) :
		_warnings++;
		break;

	case(SEV_MESSAGE) :
		_messages++;
		break;

	default:
		throw new InternalError(TEXT("Invalid Severity at ErrRep::Set"));
	}
}

void ErrRep::Set(TokErr err, unsigned long line, unsigned long col)
{
	// Get error
	TokEx tokEx(err, line, col);

	// Add to error list
	_list_errors.push_back(tokEx);

	// Set error counter
	switch (tokEx.GetSev())
	{
	case(SEV_FATAL) :
		_fatal_errors++;
		break;

	case(SEV_ERROR) :
		_errors++;
		break;

	case(SEV_WARNING) :
		_warnings++;
		break;

	case(SEV_MESSAGE) :
		_messages++;
		break;

	default:
		throw new InternalError(TEXT("Invalid severity at ErrRep::Set"));
	}
}

/////////////////////////////////////////////////////////////////////////////
// Append: Appends class
/////////////////////////////////////////////////////////////////////////////
void ErrRep::Append(const ErrRep& rhs)
{
	// Append error list
	for (list<TokEx>::const_iterator i = rhs._list_errors.begin(); i != rhs._list_errors.end(); i++)
	{
		_list_errors.push_back(static_cast<TokEx>(*i));
	}

	// Update statistics
	_fatal_errors += rhs._fatal_errors;
	_errors += rhs._errors;
	_warnings += rhs._warnings;
	_messages += rhs._messages;
}

void ErrRep::Append(const TokEx& rhs)
{
	// Get the error
	_list_errors.push_back(rhs);

	// Update error count
	switch (rhs.GetSev())
	{
	case(SEV_FATAL) :
		_fatal_errors++;
		break;

	case(SEV_ERROR) :
		_errors++;
		break;

	case(SEV_WARNING) :
		_warnings++;
		break;

	case(SEV_MESSAGE) :
		_messages++;
		break;

	default:
		throw new InternalError(TEXT("Invalid type in ErrRep::Append"));
	}
}

///////////////////////////////////////////////////////////////////////////////
// PrintBanner: Print Copyright notice
///////////////////////////////////////////////////////////////////////////////
void ErrRep::PrintBanner()
{
#ifdef _UNICODE
	wcerr << TEXT("Book of Angels: VASM (Virtual ASeMbler)") << endl;
	wcerr << TEXT("Version: ") << VASM_VERSION << endl;
	wcerr << TEXT("(c) Copyright 2013 Edward Principe") << endl;
	wcerr << TEXT("All Rights Reserved") << endl;
#else
	cerr << TEXT("Book of Angels: VASM (Virtual ASeMbler)") << endl;
	cerr << TEXT("Version: ") << VASM_VERSION << endl;
	cerr << TEXT("(c) Copyright 2013 Edward Principe") << endl;
	cerr << TEXT("All Rights Reserved") << endl;
#endif

}


////////////////////////////////////////////////////////////////////////////////
// PrintReport: Reports errors
///////////////////////////////////////////////////////////////////////////////
void ErrRep::PrintReport()
{
	// Print Errrors
	for (list<TokEx>::iterator i = _list_errors.begin(); i != _list_errors.end(); i++)
	{
#ifdef _UNICODE
		wcout << TEXT("(") << i->GetLine() << TEXT(" , ") << i->GetCol() << TEXT("): ") << i->MakeMsg() << endl;
#else
		cout << TEXT("(") << i->GetLine() << TEXT(" , ") << i->GetCol() << TEXT("): ") << i->MakeMsg() << endl;
#endif
	}

	// Print stats
#ifdef _UNICODE
	wcerr << TEXT("Fatal Errors: ") << _fatal_errors << endl;
	wcerr << TEXT("Errors: ") << _errors << endl;
	wcerr << TEXT("Warnings: ") << _warnings << endl;
	wcerr << TEXT("Messages: ") << _messages << endl;
#else
	cerr << TEXT("Fatal Errors: ") << _fatal_errors << endl;
	cerr << TEXT("Errors: ") << _errors << endl;
	cerr << TEXT("Warnings: ") << _warnings << endl;
	cerr << TEXT("Messages: ") << _messages << endl;
#endif
}